package com.tegtech.tools.aliyun.support;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.Map;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PolicyConditions;
import com.google.common.collect.Maps;
import com.tegtech.common.utils.FileUtils;
import com.tegtech.tools.aliyun.properties.AliyunProperties;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;

/**
 * OSS文件操作类
 * @Author Jun
 * @date 2020年4月7日 下午5:39:09
 */
public class OSSFiles {

	/**
	 * url签名默认过期时长3小时(单位：毫秒)
	 */
	private static final long EXPIRE = 10800000L;
	
	/**
	 * 视频截图参数
	 */
	public static final String VIDEO_SCREENSHOT_PARAMS = "?x-oss-process=video/snapshot,t_0,w_0,h_0";
	
	/**
	 * 获取OSS客户端
	 * @return
	 */
	public static OSS getClient() {
		return new OSSClientBuilder().build(AliyunProperties.getOssEndpoint(), AliyunProperties.getAccessId(), AliyunProperties.getAccessSecret());
	}
	
	/**
	 * 文件上传前获取OSS的签名
	 *
	 * @param folder
	 * @param format
	 * @return
	 */
	public static Map<String, Object> getSignature(String folder, String format) {
		OSS client = getClient();
		Map<String, Object> respMap = Maps.newLinkedHashMap();
		try {
			Long expireEndTime = System.currentTimeMillis() + EXPIRE;// 过期时间
			String key = getFileKey(folder, format); // 上传到OSS的key

			PolicyConditions policyConds = new PolicyConditions();
			policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
			policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, key);

			String postPolicy = client.generatePostPolicy(new Date(expireEndTime), policyConds);

			String encodedPolicy = BinaryUtil.toBase64String(postPolicy.getBytes("utf-8"));
			String postSignature = client.calculatePostSignature(postPolicy);

			respMap.put("OSSAccessKeyId", AliyunProperties.getAccessId());
			respMap.put("policy", encodedPolicy);
			respMap.put("signature", postSignature);
			respMap.put("key", key);
			respMap.put("host", AliyunProperties.getOssHost());
			respMap.put("expire", String.valueOf(expireEndTime / 1000));
			respMap.put("success_action_status", "200");// 让服务端返回200,不然，默认会返回204
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			client.shutdown();
		}
		return respMap;
	}

	/**
	 * 文件是否存在
	 *
	 * @param filePath   文件完整路径 如:myfile/log/mylog.log
	 * @return true(存在),false(不存在)
	 */
	public static boolean isExists(String filePath) {
		OSS ossClient = getClient();
		boolean found = false;
		try {
			found = ossClient.doesObjectExist(AliyunProperties.getOssBucket(), filePath);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			ossClient.shutdown();
		}
		return found;
	}

	/**
	 * 根据key删除OSS文件
	 *
	 * @param key
	 * @throws IOException
	 */
	public static void deleteFile(String key) {
		OSS client = getClient();
		try {
			client.deleteObject(AliyunProperties.getOssBucket(), key);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			client.shutdown();
		}
	}
	
	/**
	 * 根据文件的URL上传文件到OSS
	 *
	 * @param url
	 * @param folder
	 * @return
	 * @throws Exception
	 */
	public static String fileUploadByUrl(String url, String folder) throws Exception {
		if(StrUtil.isNotBlank(url) && url.startsWith("http:")) {
			url = url.replaceFirst("http", "https");
		}
		return uploadInputStream(new URL(url).openStream(), folder, FileUtils.getNameWithExtension(url));
	}
	
	/**
	 * 根据文件的URL上传文件到OSS
	 *
	 * @param url
	 * @param folder
	 * @param format
	 * @return
	 * @throws Exception
	 */
	public static String fileUploadByUrl(String url, String folder, String format) throws Exception {
		if(StrUtil.isNotBlank(url) && url.startsWith("http:")) {
			url = url.replaceFirst("http", "https");
		}
		return uploadInputStream(new URL(url).openStream(), folder, format);
	}

	/**
	 * 直接将文件上传到OSS
	 *
	 * @throws Exception
	 */
	public static String fileUploadByFile(File file, String folder) throws Exception {
		return uploadInputStream(new FileInputStream(file), folder, file.getName());
	}

	/**
	 * 直接将文件上传到OSS
	 *
	 * @throws FileNotFoundException
	 * @throws Exception
	 */
	public static String fileUpload(File file, String key) throws Exception {
		return uploadInputStream(new FileInputStream(file), key);
	}

	/**
	 * 上传文件流到oss
	 *
	 * @param is
	 * @param folder
	 * @param fileName 文件格式 如"jpg"
	 * @return
	 * @throws IOException
	 */
	public static String uploadInputStream(InputStream inputStream, String folder, String format) {
		return uploadInputStream(inputStream, OSSFiles.getFileKey(folder, format));
	}

	/**
	 * 上传文件流到oss
	 * @param inputStream
	 * @param key
	 * @return 文件在oss显示全路径
	 */
	public static String uploadInputStream(InputStream inputStream, String key) {
		// 创建OSSClient实例
		OSS client = getClient();
		try {
			client.putObject(AliyunProperties.getOssBucket(), key, inputStream);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			client.shutdown();
		}
		return AliyunProperties.getOssHost() + "/" + key;
	}
	
	/**
	 * 从OSS下载文件
	 * @param fileKey
	 * @return
	 */
	public static InputStream dowload(String fileKey) {
		OSS client = getClient();
		try {
			OSSObject object = client.getObject(new GetObjectRequest(AliyunProperties.getOssBucket(), fileKey));
			return object.getObjectContent();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 生成文件key(重置文件名)
	 *
	 * @param folder	 	上传到oss文件夹名称
	 * @param format		文件格式
	 * @return
	 */
	public static String getFileKey(String folder, String format) {
		int index = format.lastIndexOf(".");
		format = (index == -1) ? format : format.substring(index + 1, format.length());
		return new StringBuffer(folder).append("/").append(IdUtil.fastSimpleUUID()).append(".").append(format).toString();
	}

}
